package com.sigmatrix.h5.auth;

import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.sigmatrix.h5.components.FeignManager;
import com.sigmatrix.h5.dao.EnterpriseDao;
import com.sigmatrix.h5.entity.DisDealerAcct;
import com.sigmatrix.h5.entity.Enterprise;
import com.sigmatrix.h5.enums.CrmAcctType;
import com.sigmatrix.h5.enums.RebateTarget;
import com.sigmatrix.h5.enums.SysResModule;
import com.sigmatrix.h5.enums.UserType;
import com.sigmatrix.h5.exception.MessageException;
import com.sigmatrix.h5.feign.mode.CoinDto;
import com.sigmatrix.h5.feign.mode.WechatAuthorizerConfig;
import com.sigmatrix.h5.service.DisDealerAcctService;
import com.sigmatrix.h5.utils.Assert;
import com.sigmatrix.h5.utils.CommonUtils;
import com.sigmatrix.h5.utils.Cons;
import com.sigmatrix.h5.utils.JacksonUtil;
import com.sigmatrix.h5.utils.MD5Utils;
import com.sigmatrix.h5.web.args.LoginParam;
import com.sigmatrix.h5.web.mode.Login;
import com.sigmatrix.sc.jdbc.common.lang.Session;

/**
 * 用于h5
 * 
 * 使用redis作为session存储介质
 * 
 * @author wei.wang
 *
 */
@Service
public class H5Authenticator extends DefaultAuthenticator {
	private static Logger logger = LoggerFactory.getLogger(H5Authenticator.class);

	@Autowired
	private EnterpriseDao enterpriseDao;

	@Autowired
	private DisDealerAcctService disDealersAcctService;

	@Autowired
	private FeignManager feignClients;
	

	@Override
	public AuthenticationInfo authenticate(LoginParam param) {
		DisDealerAcct acct = disDealersAcctService.findByUserName(param.getLoginName());
		
		Assert.notNull(acct, "用户名或密码错误");//账号错误,没有此用户
		
		if(Cons.STATUS_ENABLE != acct.getStatus()){
			throw new MessageException("账号不可用");//用户名或密码错误
		}
		
		if (!MD5Utils.getMD5Code(param.getLoginPwd()).equals(acct.getPwd())){			
			throw new MessageException("用户名或密码错误");//密码错误
		}
		
		Assert.notNull(acct.getEnterpriseId(), "无效的用户,企业id为空");
		
		Assert.notNull(acct.getName(), "无效的用户,姓名为空");
		
		AuthenticationInfo authenInfo = new AuthenticationInfo();
		authenInfo.setLoginType(param.getLoginType());
		authenInfo.setAcctId(acct.getId());
		authenInfo.setLoginName(param.getLoginName());
		authenInfo.setEseId(acct.getEnterpriseId());
		authenInfo.setPhoneNumber(acct.getContact());
		authenInfo.setAcctType(acct.getAcctType());
		authenInfo.setUserType(acct.getUserType());
		
		if(CrmAcctType.isDealerAcct(acct.getAcctType())){
			authenInfo.setDealerOrShopId(acct.getDealerId());
		}
		if(CrmAcctType.isShopAcct(acct.getAcctType())){
			authenInfo.setDealerOrShopId(acct.getTerminalShopId());
		}
		
		// 获取公司相关信息
		Enterprise enterprise = enterpriseDao.findById(authenInfo.getEseId());
		Assert.notNull(enterprise, "无效的用户,企业ID错误");
		Assert.notNull(enterprise.getBasicModuleId(), "无效的企业,basicMoudleId为空");
		Assert.notNull(enterprise.getCode(), "无效的企业,code为空");
		authenInfo.setEseCode(enterprise.getCode());
		authenInfo.setEseName(enterprise.getName());
		authenInfo.setBasicModuleEseId(enterprise.getBasicModuleId());
		authenInfo.setDealersAcctPromotionCode(acct.getDealersAcctPromotionCode());
		// 获取公司对应的公众号id
		WechatAuthorizerConfig wechatConfig = feignClients.getAppId(authenInfo.getBasicModuleEseId().longValue());
		Assert.notNull(wechatConfig, "获取appId失败");
		Assert.notNull(wechatConfig.getAuthorizerAppId(), "appId为空");
		authenInfo.setAppId(wechatConfig.getAuthorizerAppId());
		return authenInfo;
	}

	/**
	 * LoginSession--转换-->ILoginResponse
	 * 
	 * @param session
	 * @return
	 */
	public ILoginResponse convert(LoginSession session) {
		AuthenticationInfo info = session.getInfo();
		if (info == null) {
			// 系统异常
			throw new MessageException("LoginSession对象中属性info没有正确的值。");
		}
		Integer acctId = info.getAcctId();
		if (acctId == null) {
			throw new MessageException("LoginSession对象中属性info没有正确的值。");
			// 系统异常
		}
		DisDealerAcct acct = disDealersAcctService.findById(acctId);
		Login login = new Login();
		BeanUtils.copyProperties(acct, login);
		login.setUserId(acct.getId());
		login.setAccount(info.getLoginName());
		login.setEseId(acct.getEnterpriseId());
		login.setPhoneNumber(acct.getContact());

		login.setEseCode(info.getEseCode());
		login.setBasicModuleEseId(info.getBasicModuleEseId());
		login.setDealersAcctPromotionCode(info.getDealersAcctPromotionCode());
		login.setTablePreffix(info.getEseCode());
		login.setEseName(info.getEseName());
		login.setToken(session.getToken());
		login.setUserType(acct.getUserType());
		login.setAcctType(acct.getAcctType());
		login.setAppId(info.getAppId());
		
		if(CrmAcctType.TERMINAL_SHOP.value.equals(login.getAcctType())) {
			login.setDealerType(RebateTarget.TERMINAL_SHOP.value);
		}else if(CrmAcctType.ENTERPRISE.value.equals(login.getAcctType())){
			login.setDealerType(RebateTarget.SALES_MAN.value);
		}else {
			Short userType = acct.getUserType();
			if(userType==null){
				login.setDealerType(RebateTarget.SALES_MAN.value);
			}else if(UserType.ADMIN.value.equals(userType)){
				login.setDealerType(RebateTarget.DEALER.value);
			}else{
				login.setDealerType(RebateTarget.SALES_MAN.value);
			}
		}
		
		
		if(SysResModule.REBATE.code.equals(info.getLoginType())){
			rebateLogin(login, acct);
		}
		
		String loginStr = JSONObject.toJSONString(login);
		logger.info("登陆信息：{}",loginStr);
		redisClient.set(session.getToken(), loginStr,EXPIRE_TIMEOUT, EXPIRE_TIME_UNIT);
		
		String sessionStr = JacksonUtil.write2JsonString(session);
		redisClient.set(SESSION_PREFIX+login.getEseCode()+"_"+login.getUserId(), sessionStr, EXPIRE_TIMEOUT, EXPIRE_TIME_UNIT);
		return login;
	}
	
	@Override
	public void logout(String token) {
		super.logout(token);
		redisClient.delete(token);
	}
	/**
	 * 填充返利信息。
	 * @param login
	 * @param acct
	 */
	private void rebateLogin(Login login,DisDealerAcct acct) {
		Session.set(login);
		//获取零钱包参数
		CoinDto dto = feignClients.findCoin(login.getBasicModuleEseId());
		if(CommonUtils.isNotEmpty(dto)){
			login.setAppId(dto.getToAppId());
			login.setMaxCount(dto.getMaxAmount()==null?0D:dto.getMaxAmount().doubleValue()*0.01);
			login.setMinCount(dto.getMinAmount()==null?0D:dto.getMinAmount().doubleValue()*0.01);
			login.setMinUnit(dto.getMinUnit()==null?0D:dto.getMinUnit().doubleValue()*0.01);
		}
		Session.clear();
	}
	
	
	/**
	 * 缓存 -图文验证码
	 * @param vcode
	 */
	public void cacheVcode(String vcode){
		if(vcode==null){
			return ;
		}
		redisClient.set(IMAGE_V_CODE_PREFIX+vcode.toUpperCase(), vcode, 10, TimeUnit.MINUTES);
	}
	
	/**
	 * 校验 -图文验证
	 * 
	 * @param vcode
	 * @return
	 */
	public boolean verifyVCode(String vcode){
		if(vcode==null){
			return false;
		}
		return StringUtils.isNotEmpty(redisClient.get(IMAGE_V_CODE_PREFIX+vcode.toUpperCase()));
	}
	

}
